
/**
 * 
 */

/**
 * @author arpitagarwal
 * Copyright 2012, held by Arpit Agarwal, of University of Illinois at Urbana-Champaign. 
 */

package server;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.ArrayList;

import runner.Message;

public class WorkerRunnable implements Runnable {

	protected Socket clientSocket = null;
	protected String serverText = null;
	DataInputStream dataInputStream = null;
	PrintStream printStream = null;
	long previousTimeRight;
	long previousTimeLeft;
	public static final int MIN_TIME_BW_PINGS = 5000;
	int serverPort;
	private String messageReceived;
	private boolean isLeftDead;
	private boolean isRightDead;

	public synchronized String getMessageReceived() {
		if (this.messageReceived != null) {
			String returnMessage = this.messageReceived; 
			this.messageReceived = ""; 
			return returnMessage;
		}
		else {
			return ""; 
		}
	}

	public synchronized void setMessageReceived(String str) {
		this.messageReceived += str + ";";
	}

	public WorkerRunnable(Socket clientSocket, String serverText) {
		this.clientSocket = clientSocket;
		this.serverText = serverText;
		this.previousTimeLeft = System.currentTimeMillis();
		this.previousTimeRight = System.currentTimeMillis();
		this.isLeftDead = false;
		this.isRightDead = false; 
	}

	public String getInputMessage() {
		char ch;
		String inputString = "";
		try {
			if (this.isLeftDead) {
				setMessageReceived(formNewLeftDeadMessage()); 
			}
			
			if (dataInputStream.available() > 0) {
				ch = (char) dataInputStream.read();
				if (ch == '#') {
					ch = (char) dataInputStream.read();
					while (ch != -1 && ch != '$') {
						inputString = inputString + ch;
						ch = (char) dataInputStream.read();
					}
				}
				setMessageReceived(inputString);
				return inputString;
			} else {
				inputString = "";
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
//		setMessageReceived(inputString);
		return inputString;
	}

	public String formNewLeftDeadMessage() {
		String returnMessage = "";
		returnMessage = returnMessage + "reconnect_left_dead:" + Message.getMyIP() + ":" + "decideDestination" + ":" + "noKey:noValue:" + System.currentTimeMillis() + ":1:noMessage";
		return returnMessage; 
	}
	
	public String isAnybodyDead(long time) {

		if (time - previousTimeRight > MIN_TIME_BW_PINGS) {
			this.previousTimeRight = System.currentTimeMillis(); 
			MultiThreadedServer
					.print("HELP. Right is disconnected. IP address was "
							+ clientSocket.getInetAddress().getHostAddress()
							+ ":" + clientSocket.getPort());
			return "right";
		}

		if (time - previousTimeLeft > MIN_TIME_BW_PINGS) {
			this.previousTimeLeft = System.currentTimeMillis(); 
			MultiThreadedServer
					.print("HELP. Left is disconnected. IP address was "
							+ clientSocket.getInetAddress().getHostAddress()
							+ ":" + clientSocket.getPort());
			return "left";
		}

		return "none";
	}

	public void run() {
		try {
			while (true) {
				this.dataInputStream = new DataInputStream(
						clientSocket.getInputStream());
				this.printStream = new PrintStream(
						clientSocket.getOutputStream());
				long time = System.currentTimeMillis();

				String inputString = getInputMessage();

				if (inputString.length() < 5) {
					// System.out.println(inputString);
					continue;
				}

				if (inputString.split(":")[0].equalsIgnoreCase("left")) {
					previousTimeLeft = System.currentTimeMillis();
					// MultiThreadedServer.print("Message received: " +
					// inputString);
				} else if (inputString.split(":")[0].equalsIgnoreCase("right")) {
					previousTimeRight = System.currentTimeMillis();
					// MultiThreadedServer.print("Message received: " +
					// inputString);
				}
				
				String deadDeclaration = isAnybodyDead(time);
				
				if (!deadDeclaration.equals("none")) {
					if (deadDeclaration.equalsIgnoreCase("right")) {
						this.isLeftDead = false; 
						this.isRightDead = true; 
					} else if (deadDeclaration.equalsIgnoreCase("left")) {
						this.isLeftDead = true; 
						this.isRightDead = false; 
					}
					MultiThreadedServer.print("Machine " + deadDeclaration
							+ " dead Time difference: Left: "
							+ (time - previousTimeLeft) + ", right: "
							+ (time - previousTimeRight));
				}

				 MultiThreadedServer.print("Request processed. @Time-" + time
				 + ", Data is- " + inputString);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}